#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<dirent.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<time.h>
#include<pwd.h>
#include<grp.h>

char *uid_to_name(uid_t uid)
{
   struct passwd * getpwuid(),*pw_ptr;
   static char numstr[10];

   if((pw_ptr= getpwuid(uid))==NULL)
   {
       sprintf(numstr,"%d",uid);
       return numstr;
   }
   else
       return pw_ptr->pw_name;
}

char *gid_to_name(gid_t gid)
{
   struct group *getgrgid(),*grp_ptr;
   static char numstr[10];
   if((grp_ptr=getgrgid(gid))==NULL)
   {
       sprintf(numstr,"%d",gid);
       return numstr;
   }
   else
       return grp_ptr->gr_name;
}

int find_mid(char(*data)[512], int l, int r)
{
    int mid = (l + r) / 2;
    if(strcmp(data[l], data[mid]) > 0)
    {
        int t = l;
        l = mid;
        mid = t;
    }
    if(strcmp(data[mid], data[r]) > 0)
    {
        int t = mid;
        mid = r;
        r = t;
    }
    return mid;
}

void swap(char *a, char *b)
{
    char t[512];
    strcpy(t, a);
    strcpy(a, b);
    strcpy(b, t);
}
void sort(char(*data)[512], int l, int r)
{
    while(l < r)
    {
        int x = l, y = r;
        int mid = find_mid(data, l, r);
        do
        {
            while(strcmp(data[y], data[mid]) > 0)
                y--;
            while(strcmp(data[x], data[mid]) < 0)
                x++;
            if(x <= y)
            {
                swap(data[x++], data[y--]);
            }
        }
        while(x <= y);
        sort(data, x, r);
        r = y;
    }
}
int check_filename_color(int mode_bit)
{
    int file_type = (mode_bit & 0170000);
    if(file_type == 0040000) return 2;
    if(mode_bit & 0000111) return 1;
    return 0;
}

void printdir(char* dirname, int is_all)
{
    char pathname[512];
    char names[256][512];
    int cnt_name = 0;
    DIR* dir;
    struct dirent* dp;
    struct stat st;
    if(!(dir = opendir(dirname)))
    {
        perror("opendir");
        exit(1);
    }
    //weather filter "." ".."
    while(dp = readdir(dir))
    {
        if(!is_all && dp -> d_name[0] == '.')
            continue;
        strcpy(names[cnt_name++], dp -> d_name);
    }

    sort(names, 0, cnt_name - 1);
    //printf("[%s]\n", names[0]);

    for(int i = 0; i < cnt_name; i++)
    {
        sprintf(pathname, "%s/%s", dirname, names[i]);
        if(stat(pathname, &st) == -1)
        {
            perror("stat");
            exit(1);
        }
        int filename_color = check_filename_color(st.st_mode);
        if(filename_color == 1)
        {
            printf("\33[1;32m%s\33[0m  ", pathname + 2);
        }
        else if(filename_color == 2)
        {
            printf("\33[1;34m%s\33[0m  ", pathname + 2);
        }
        else printf("%s  ", pathname + 2);

    }
    closedir(dir);
    printf("\n");
}
int main(int argc, char* argv[])
{
    int is_all = 0;
    if(argc == 1)
    {
        printdir(".", is_all);
        return 0;
    }
    if(argc > 1)
    {
        for(int i = 1; i < argc; i++)
        {
            if(argv[i][0] != '-') continue;
            for(int j = 1; argv[i][j]; j++)
            {
                if(argv[i][j] == 'a') is_all = 1;
                else
                {
                    printf("invalid option, please check again!\n");
                    exit(1);
                }
            }
        }
    }
    int flag = 0;
    for(int i = 1; i < argc; i++)
    {
        if(argv[i][0] == '-') continue;
        flag = 1;
        printdir(argv[i], is_all);
    }
    if(!flag) printdir(".", is_all);
    return 0;
}
